/***************************************************************************
 *            modelica-grammar.hpp
 *
 *  Sat Mar 14 21:50:13 2009
 *  Copyright  2009  Jorge Eduardo Cardona Gaviria
 *  <jorgeecardona@gmail.com>
 ****************************************************************************/

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */
 
#ifndef _MODELICA_GRAMMAR_HPP_
#define _MODELICA_GRAMMAR_HPP_

//#define PHOENIX_LIMIT 10
//#define BOOST_SPIRIT_CLOSURE_LIMIT 10

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
//#include <boost/lambda/lambda.hpp>
//#include <boost/bind.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/foreach.hpp>



#include "modelica.hpp"

#include <gtkmm.h>
#include <iostream>
#include <string>
#include <fstream>

using namespace boost::spirit;
using namespace boost::spirit::qi;
using namespace boost::spirit::ascii;
using namespace boost::spirit::arg_names;

namespace phoenix = boost::phoenix;
namespace fusion = boost::fusion;

Modelica::Stored read_string(string content);

// Boost::Fusion definition of the stored class.
BOOST_FUSION_ADAPT_STRUCT(
    Modelica::Stored,
    (std::string, within)
    (std::vector<Modelica::Class*>, classes)
)

// Boost::Fusion definition of the class class. :)
BOOST_FUSION_ADAPT_STRUCT(
	Modelica::Class,
	(std::string, name)
)

template <typename Iterator>
struct ModelicaGrammar : grammar<Iterator, Modelica::Stored(), space_type>
{	
	ModelicaGrammar();

	symbols<char,unsigned>  KEYWORDS_TABLE;

    rule<Iterator, space_type>  KEYWORDS , K_ALGORITHM ,  K_AND ,  K_ANNOTATION ,  K_ASSERT ,  K_BLOCK ,  K_BREAK ,  K_CLASS ,  K_CONNECT ,  K_CONNECTOR ,  K_CONSTANT ,  K_CONSTRAINEDBY , 
                    K_DER ,  K_DISCRETE ,  K_EACH ,  K_ELSE ,  K_ELSEIF ,  K_ELSEWHEN ,  K_ENCAPSULATED ,  K_END ,  K_ENUMERATION ,  K_EQUATION ,  K_EXPANDABLE ,  
                    K_EXTENDS ,  K_EXTERNAL ,  K_FALSE ,  K_FINAL ,  K_FLOW ,  K_FOR ,  K_FUNCTION ,  K_IMPORT ,  K_IF ,  K_IN ,  K_INITIAL ,  K_INNER ,  K_INPUT ,  
                    K_LOOP ,  K_MODEL ,  K_NOT ,  K_OR ,  K_OUTER ,  K_OUTPUT ,  K_PACKAGE ,  K_PARAMETER ,  K_PARTIAL ,  K_PROTECTED ,  K_PUBLIC ,  K_RECORD ,  
                    K_REDECLARE ,  K_REPLACEABLE ,  K_RETURN ,  K_THEN ,  K_TRUE ,  K_TYPE ,  K_WHEN ,  K_WHILE ,  K_WITHIN,

                    // B.1
                    NONDIGIT, DIGIT, /*IDENT,*/ UNSIGNED_INTEGER, UNSIGNED_NUMBER, S_ESCAPE, S_CHAR, STRING, Q_CHAR, Q_IDENT,
                    
					// B.2.1    
            		/*stored_definition,*/
                    
					// B.2.2       
					/*class_definition, class_specifier,*/ base_prefix, enum_list, enumeration_literal, /*composition,*/ language_specification, external_function_call, 
                    /*element_list, element,*/ import_clause,
                    
					// B.2.3
                    extends_clause, constraining_clause,
                    
					// B.2.4
                    /*component_clause, type_prefix,*/ type_specifier, component_list, component_declaration, conditional_attribute, declaration,
                    
					// B.2.5
                    modification, class_modification, argument_list, argument, element_modification_or_replaceable, element_modification, element_redeclaration, 
                    element_replaceable, component_clause1, component_declaration1,
                    
					// B.2.6
                    equation_section, algorithm_section, equation, statement, if_equation, if_statement, for_equation, for_statement, for_indices, for_index,
                    while_statement, when_equation, when_statement, connect_clause,
                    
					// B.2.7
                    expression, simple_expression, logical_expression, logical_term, logical_factor, relation, rel_op, arithmetic_expression, add_op, term, mul_op,
                    factor, primary, /*name,*/ component_reference, function_call_args, function_arguments, named_arguments, named_argument, output_expression_list,
                    expression_list, array_subscripts, subscript, comment, /*string_comment,*/ annotation;

	rule<Iterator, std::string(), space_type> IDENT;
	// B.2.1
	rule<Iterator, Modelica::Stored(), space_type> stored_definition;

	// B.2.2	
	rule<Iterator, Modelica::Class*(), 
		locals<bool/*encapsulated*/, bool/*partial*/, bool/*expandable connector*/>, 
		space_type> class_definition;

	rule<Iterator, void(Modelica::Class*), space_type> class_specifier;
	rule<Iterator, void(Modelica::Class*), space_type> composition;
	rule<Iterator, void(Modelica::Class*, bool/*protected*/), space_type> element_list;
	rule<Iterator, Modelica::Element*(), locals<bool,bool,bool,bool>, space_type> element;

	// B.2.4
	rule<Iterator, Modelica::Component*(bool,bool,bool,bool,bool), space_type> component_clause;
	rule<Iterator, /*void(Modelica::Prefix*),*/ space_type> type_prefix;

	// B.2.7
	rule<Iterator, std::string(), space_type> name;
	rule<Iterator, std::string(), space_type> string_comment;

};

#endif /* _MODELICA_GRAMMAR_HPP_ */
